//
//  ContactHelper.m
//  Contacts
//
//  Created by nsm on 2017/10/16.
//  Copyright © 2017年 beisheng. All rights reserved.
//

#import "ContactHelper.h"

@interface ContactHelper ()
{
    ABAddressBookRef _addressBook;
}
@property (nonatomic, strong) NSArray *keysToFetch;
@end

@implementation ContactHelper

- (void)dealloc {
    if (@available(iOS 9.0, *)) {
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:CNContactStoreDidChangeNotification
                                                      object:nil];
    } else {
        ABAddressBookUnregisterExternalChangeCallback(_addressBook, externalDidChange, NULL);
        if (_addressBook) {
            CFRelease(_addressBook);
            _addressBook = NULL;
        }
    }
}

- (instancetype)init {
    self = [super init];
    if (self) {
        if (@available(iOS 9.0, *)) {
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(contactStoreDidChange)
                                                         name:CNContactStoreDidChangeNotification
                                                       object:nil];
        } else {
            _addressBook = ABAddressBookCreate();
            ABAddressBookRegisterExternalChangeCallback(_addressBook, externalDidChange, NULL);
        }
    }
    return self;
}

+ (instancetype)sharedInstance {
    static ContactHelper *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [self new];
    });
    return instance;
}

- (NSArray *)keysToFetch {
    if (@available(iOS 9.0, *)) {
        if (!_keysToFetch) {
            _keysToFetch = @[[CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName],
                             CNContactPhoneNumbersKey,
                             CNContactOrganizationNameKey,
                             CNContactDepartmentNameKey,
                             CNContactJobTitleKey,
                             CNContactNoteKey,
                             CNContactPhoneticGivenNameKey,
                             CNContactPhoneticFamilyNameKey,
                             CNContactPhoneticMiddleNameKey,
                             CNContactImageDataKey,
                             CNContactThumbnailImageDataKey,
                             CNContactEmailAddressesKey,
                             CNContactPostalAddressesKey,
                             CNContactBirthdayKey,
                             CNContactNonGregorianBirthdayKey,
                             CNContactInstantMessageAddressesKey,
                             CNContactSocialProfilesKey,
                             CNContactRelationsKey,
                             CNContactUrlAddressesKey];
        }
    }
    return _keysToFetch;
}

- (void)requestContactsAuthorization:(void (^)(BOOL))completion {
    
    if (@available(iOS 9.0, *)) {
        CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
        switch (status) {
            case CNAuthorizationStatusNotDetermined:
            {
                CNContactStore *store = [CNContactStore new];
                [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError *error) {
                    !completion?:completion(granted);
                }];
            }
                break;
            case CNAuthorizationStatusAuthorized:
                !completion?:completion(YES);
                break;
            default:
                !completion?:completion(NO);
                break;
        }
    } else {
        switch (ABAddressBookGetAuthorizationStatus()) {
            case kABAuthorizationStatusNotDetermined:
            {
                ABAddressBookRef ref = ABAddressBookCreate();
                ABAddressBookRequestAccessWithCompletion(ref, ^(bool granted, CFErrorRef error) {
                    CFRelease(ref);
                    !completion?:completion(granted);
                });
            }
                break;
            case kABAuthorizationStatusAuthorized:
                !completion?:completion(YES);
                break;
            default:
                !completion?:completion(NO);
                break;
        }
    }
}



- (void)fetchContacts:(void (^)(BOOL, NSArray<Contacter *> *))completion {
    [self requestContactsAuthorization:^(BOOL success) {
        if (!success) return !completion?:completion(NO, nil);
        
        if (@available(iOS 9.0, *)) {
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                NSMutableArray *array = [NSMutableArray new];
                CNContactStore *store = [CNContactStore new];
                CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:self.keysToFetch];
                [store enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
                    [array addObject:[Contacter contacterWithCNContact:contact]];
                }];
                dispatch_async(dispatch_get_main_queue(), ^{
                    !completion?:completion(YES, array);
                });
            });
        } else {
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                NSMutableArray *array = [NSMutableArray new];
                ABAddressBookRef abRef = ABAddressBookCreate();
                CFArrayRef arrayRef = ABAddressBookCopyArrayOfAllPeople(abRef);
                CFIndex count = CFArrayGetCount(arrayRef);
                for (int i=0; i<count; i++) {
                    ABRecordRef recordRef = CFArrayGetValueAtIndex(arrayRef, i);
                    [array addObject:[Contacter contacterWithRecordRef:recordRef]];
                }
                CFRelease(abRef);
                CFRelease(arrayRef);
                dispatch_sync(dispatch_get_main_queue(), ^{
                    !completion?:completion(YES, array);
                });
            });
        }
    }];
}

- (void)contactStoreDidChange {
    
}

void externalDidChange(ABAddressBookRef addressBook, CFDictionaryRef info, void *context) {
    
}

@end
